﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SkyDriveConnector.ListsService;
using System.Xml.Linq;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using System.Windows.Browser;
using System.Threading;
using Microsoft.SharePoint.Client;


namespace SkyDriveConnector
{
    public class SharePointModel : IConnectorOperations
    {
        ListsSoapClient proxy; // = new ListsSoapClient();
        XNamespace ns = "http://schemas.microsoft.com/sharepoint/soap/";
        XNamespace rowns = "#RowsetSchema";
        SkyDriveList _skydrivelist;


        public string AuthToken
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public event EventHandler<EventArgs> SkyDriveItemsLoadingComplete;

        public event EventHandler<EventArgs> SharePointItemsLoadingComplete;

        public event EventHandler<EventArgs> AddSkyDriveFolderComplete;

        public event EventHandler<EventArgs> AddSharePointFolderComplete;

        public event EventHandler<EventArgs> AddSkyDriveItemComplete;

        public event EventHandler<EventArgs> AddSharePointItemComplete;

        public event EventHandler<EventArgs> DeleteSkyDriveItemComplete;

        public event EventHandler<EventArgs> DeleteSharePointItemComplete;

        public event EventHandler<ItemLoadingErrorEventArgs> SkyDriveItemLoadingOnError;

        public event EventHandler<ItemLoadingErrorEventArgs> SharePointItemLoadingOnError;

        //public event EventHandler<EventArgs> ItemsLoadingComplete;

        //public event EventHandler<EventArgs> AddNewItemComplete;

        //public event EventHandler<EventArgs> DeleteItemComplete;

        //public event EventHandler<ItemLoadingErrorEventArgs> ItemLoadingOnError;
        App currentApp = (App)App.Current;


        Dictionary<string, int> CorrelationIds = new Dictionary<string, int>();
        //ClientContext clientCtx;


        public SharePointModel()
        {
            proxy = new ListsSoapClient();
            proxy.Endpoint.Address = new System.ServiceModel.EndpointAddress(SPHelpers.GetUrl() + "/_vti_bin/lists.asmx");
            //clientCtx = new ClientContext("http://anildwa-win8/sites/testsite");
            //_skydrivelist = new SkyDriveList();
            //_skydrivelist.ListName = "SkyDriveList";
            proxy.GetListAndViewCompleted += GetListAndView_Completed;
            proxy.GetListItemsCompleted += GetListItems_Completed;
            //proxy.UpdateListItemsCompleted += UpdateListItems_Completed;


            if (!currentApp.Cache.ContainsKey("_skydrivelist"))
            {
                _skydrivelist = new SkyDriveList();
                _skydrivelist.ListName = "SkyDriveList";
                currentApp.Cache.Add("_skydrivelist", _skydrivelist);
                proxy.GetListAndViewAsync(_skydrivelist.ListName, "");
                
            }
            else
            {
                _skydrivelist = (SkyDriveList)currentApp.Cache["_skydrivelist"];

            }
            
        }

      

        public void GetSingleItem(string ItemId, int CorrelationId)
        {
            _skydrivelist.SkyDriveObjectId = ItemId;
            while (!_skydrivelist.IsPopulated)
            {
                Thread.Sleep(500);
            }

            GetListItems(_skydrivelist, CorrelationId);
       
        }

        public void AddNewItem(string path, SkyDriveObject skydriveObject, int CorrelationId)
        {

            while (!_skydrivelist.IsPopulated)
            {
                Thread.Sleep(500);
            }

            AddSharePointItem(path, skydriveObject, CorrelationId);

        }



        private void AddSharePointItem(string path,SkyDriveObject skydriveObject, int CorrelationId)
        {
            Batch batch = GetUpdateListSchema("New");

            Field idField = new Field();
            idField.Name = "ID";
            idField.Value = "New";


            Field fsobjecttype = new Field();
            fsobjecttype.Name = "FSObjType";
            fsobjecttype.Value = "0";

            Field basename = new Field();
            basename.Name = "BaseName";
            basename.Value = path +  skydriveObject.name;


            Field titleField = new Field();
            titleField.Name = "Title";
            titleField.Value = skydriveObject.name;

            Field skydriveobjectidField = new Field();
            skydriveobjectidField.Name = "SkyDriveObjectId";
            skydriveobjectidField.Value = skydriveObject.id;

            Field skydrivefileurlField = new Field();
            skydrivefileurlField.Name = "SkyDriveFileUrl";
            //skydrivefileurlField.Value = string.Format("{0}, {1}", skydriveObject.source.Split(new string[] { ",Default" }, StringSplitOptions.None)[0], skydriveObject.name);

            //folder.77ecf790debcf246.77ECF790DEBCF246!109
            //https://skydrive.live.com/redir.aspx?cid=77ecf790debcf246&page=view&resid=77ECF790DEBCF246!535&parid=77ECF790DEBCF246!105

            string skdlink;
            
            if (skydriveObject.link == null)
            {
                if (skydriveObject.parent_id.Split('.').Length > 1)
                    skdlink = string.Format("https://skydrive.live.com/redir.aspx?cid={0}&page=view&resid={1}&parid={2}", skydriveObject.id.Split('.')[1], skydriveObject.id.Split('.')[2], skydriveObject.parent_id.Split('.')[2]);
                else
                    skdlink = string.Format("https://skydrive.live.com/redir.aspx?cid={0}&page=view&resid={1}", skydriveObject.id.Split('.')[1], skydriveObject.id.Split('.')[2]);

            }
            else
            {
                skdlink = skydriveObject.link;
            }

            skydrivefileurlField.Value = string.Format("{0}, {1}", skdlink, skydriveObject.name);

            
            batch.Method.Field = new List<Field>();
            //batch.Method.Field.Add(idField);
            batch.Method.Field.Add(fsobjecttype);
            batch.Method.Field.Add(basename);
            batch.Method.Field.Add(titleField);
            batch.Method.Field.Add(skydriveobjectidField);
            batch.Method.Field.Add(skydrivefileurlField);


            string xml = SerializationHelper.ToString<Batch>(batch);
            XElement updatebatch = XElement.Parse(xml);
            if (!CorrelationIds.ContainsKey("UpdateListItemsAsync"))
            {
                CorrelationIds.Add("UpdateListItemsAsync", CorrelationId);
            }
            else
            {
                CorrelationIds["UpdateListItemsAsync"] = CorrelationId;
            }
            proxy.UpdateListItemsCompleted += UpdateListItems_Completed;

            proxy.UpdateListItemsAsync(_skydrivelist.ListName, updatebatch);
        }


        private Batch GetUpdateListSchema(string Cmd)
        {
            Method methodobj = new Method();
            methodobj.ID = "1";
            methodobj.Cmd = Cmd;

            Batch batch = new Batch();
            batch.OnError = "Continue";
            //batch.RootFolder = "/Lists/SkyDriveList/test1";

            batch.ListVersion = _skydrivelist.ListVersion;
            batch.Method = methodobj;

            return batch;
        }

        private void UpdateListItems_Completed(object sender, UpdateListItemsCompletedEventArgs e)
        {
            proxy.UpdateListItemsCompleted -= UpdateListItems_Completed; 
            if (AddSharePointItemComplete != null)
            {

                SharePointResponse spResponse = new SharePointResponse();
                if (e.Result.Descendants(ns + "ErrorText").Count() >= 1)
                    spResponse.Message = e.Result.Descendants(ns + "ErrorText").First().Value;
                else
                    spResponse.Message = e.Result.Descendants(ns + "ErrorCode").First().Value;
                List<SharePointResponse> responses = new List<SharePointResponse>();
                responses.Add(spResponse);

                ItemLoadingCompleteEventArgs<SharePointResponse> eventargs = new ItemLoadingCompleteEventArgs<SharePointResponse>(responses,
                    CorrelationIds["UpdateListItemsAsync"], string.Format("{0},ResponseCode:{1}", "SharePoint UpdateListItems Completed",spResponse.Message),"");


                AddSharePointItemComplete(this, eventargs);

                
            }

        }


        private void DeleteListItem_Completed(object sender, UpdateListItemsCompletedEventArgs e)
        {
            proxy.UpdateListItemsCompleted -= DeleteListItem_Completed;
            if (DeleteSharePointItemComplete != null)
            {

                SharePointResponse spResponse = new SharePointResponse();
                if (e.Result.Descendants(ns + "ErrorText").Count() >= 1)
                    spResponse.Message = e.Result.Descendants(ns + "ErrorText").First().Value;
                else
                    spResponse.Message = e.Result.Descendants(ns + "ErrorCode").First().Value;
                List<SharePointResponse> responses = new List<SharePointResponse>();
                responses.Add(spResponse);

                ItemLoadingCompleteEventArgs<SharePointResponse> eventargs = new ItemLoadingCompleteEventArgs<SharePointResponse>(responses,
                    CorrelationIds["UpdateListItemsAsync"], string.Format("{0},ResponseCode:{1}", "SharePoint DeleteItem Completed", spResponse.Message), "");


                DeleteSharePointItemComplete(this, eventargs);


            }

        }


        private void GetListAndView_Completed(object sender, GetListAndViewCompletedEventArgs e)
        {

            var view = (from row in e.Result.Descendants()
                        where row.Name == ns + "View"
                        select row).Single();

            var fields = from field in view.Element(ns + "ViewFields").Elements(ns + "FieldRef")
                         select field.Attribute("Name").Value;

            _skydrivelist.ViewFields = (from viewfields in view.Elements()
                                        where viewfields.Name == ns + "ViewFields"
                                        select viewfields).Single().ToString();



            _skydrivelist.ListVersion = (from row in e.Result.Descendants()
                                         where row.Name == ns + "List"
                                         select row).Single().Attribute("Version").Value;


            _skydrivelist.ViewGuid = (from row in e.Result.Descendants()
                                      where row.Name == ns + "View"
                                      select row).Single().Attribute("Name").Value;


            _skydrivelist.Fields = (from displayfield in e.Result.Elements(ns + "List").First().Elements(ns + "Fields").Elements(ns + "Field")
                                    join field in fields on displayfield.Attribute("Name").Value equals field
                                    select new
                                    {
                                        field,
                                        displayfield.Attribute("DisplayName").Value

                                    }).ToDictionary(key => "ows_" + key.field, value => value.Value);
            _skydrivelist.IsPopulated = true;


        }

        private void GetListItems(SkyDriveList skydrivelist, int CorrelationId)
        {
            XElement value = new XElement("Value", new XAttribute("Type", "Text"));
            value.Value = skydrivelist.SkyDriveObjectId; //"3452345563456346";
            XElement query = new XElement("Query", new XElement("Where",
                    new XElement("Eq", new XElement("FieldRef", new XAttribute("Name", "SkyDriveObjectId")), value)));
            
            XElement queryOptions = new XElement("QueryOptions", new XElement("ViewAttributes", new XAttribute("Scope", "Recursive")));
            if (!CorrelationIds.ContainsKey("GetListItemsAsync"))
            {
                CorrelationIds.Add("GetListItemsAsync", CorrelationId);
            }
            else
            {
                CorrelationIds["GetListItemsAsync"] = CorrelationId;
            }
            proxy.GetListItemsAsync(_skydrivelist.ListName, skydrivelist.ViewGuid, query, null, "1", queryOptions, "");

        }


        private void GetListItems_Completed(object sender, GetListItemsCompletedEventArgs e)
        {
            List<FieldValue> fieldValues = new List<FieldValue>();
            ItemLoadingCompleteEventArgs<FieldValue> eventargs = new ItemLoadingCompleteEventArgs<FieldValue>(fieldValues,
                CorrelationIds["GetListItemsAsync"], "SharePoint GetListItems Completed","");
            if (e.Result.Descendants().First().Attribute("ItemCount").Value == "0")
            {                
                SharePointItemsLoadingComplete(this, eventargs);
                return;
            }

            var items = (from row in e.Result.Descendants()
                         where row.Name == rowns + "row"
                         select row.Attributes().Where(attr => _skydrivelist.Fields.ContainsKey(attr.Name.LocalName))).Single();

            

            foreach (var item in items)
            {
                var fieldvalue = new FieldValue();
                fieldvalue.FieldDisplayName = _skydrivelist.Fields[item.Name.ToString()];
                fieldvalue.Value = item.Value;
                fieldValues.Add(fieldvalue);
            }
            if(SharePointItemsLoadingComplete!= null)
                SharePointItemsLoadingComplete(this, eventargs); 


        }

        

        public void CreateFolder(string path, string foldername,string description, int CorrelationId, string skydriveObjectId)
        {
            Batch batch = GetUpdateListSchema("New");

            Field fsobjecttype = new Field();
            fsobjecttype.Name = "FSObjType";
            fsobjecttype.Value = "1";

            Field basename = new Field();
            basename.Name = "BaseName";
            basename.Value = path + foldername;

            Field skydriveobjectidField = new Field();
            skydriveobjectidField.Name = "SkyDriveObjectId";
            skydriveobjectidField.Value = skydriveObjectId;

        
            batch.Method.Field = new List<Field>();
            batch.Method.Field.Add(fsobjecttype);
            batch.Method.Field.Add(basename);
            batch.Method.Field.Add(skydriveobjectidField);

            string xml = SerializationHelper.ToString<Batch>(batch);
            XElement updatebatch = XElement.Parse(xml);
            if (!CorrelationIds.ContainsKey("UpdateListItemsAsync"))
            {
                CorrelationIds.Add("UpdateListItemsAsync", CorrelationId);
            }
            else
            {
                CorrelationIds["UpdateListItemsAsync"] = CorrelationId;
            }

            proxy.UpdateListItemsCompleted += UpdateListItems_Completed;
            proxy.UpdateListItemsAsync(_skydrivelist.ListName, updatebatch);



        }

        
        

        public void AddNewItem(string path, FileStream filestream, string filename, int CorrelationId)
        {
            throw new NotImplementedException();
        }

        List skdlist;
        ListItemCollection item;
        public void DeleteItem(string ItemId, int CorrelationId)
        {
            Batch batch = GetUpdateListSchema("Delete");

            Field idField = new Field();
            idField.Name = "ID";
            idField.Value = ItemId;

            batch.Method.Field = new List<Field>();
            batch.Method.Field.Add(idField);
            


            string xml = SerializationHelper.ToString<Batch>(batch);
            XElement updatebatch = XElement.Parse(xml);
            if (!CorrelationIds.ContainsKey("UpdateListItemsAsync"))
            {
                CorrelationIds.Add("UpdateListItemsAsync", CorrelationId);
            }
            else
            {
                CorrelationIds["UpdateListItemsAsync"] = CorrelationId;
            }

         
            proxy.UpdateListItemsCompleted += DeleteListItem_Completed;

            proxy.UpdateListItemsAsync(_skydrivelist.ListName, updatebatch);
           
        }


        private void LoadListComplete(object sender, ClientRequestSucceededEventArgs e)
        {
           
        }


        private void LoadListFailed(object sender, ClientRequestFailedEventArgs e)
        {


        }
        public void GetItems(string Path, int CorrelationId)
        {
            throw new NotImplementedException();
        }



        
    }
}
